{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Modeling and Simulation in Python\n",
    "\n",
    "Project 1 example\n",
    "\n",
    "Copyright 2018 Allen Downey\n",
    "\n",
    "License: [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Configure Jupyter so figures appear in the notebook\n",
    "%matplotlib inline\n",
    "\n",
    "# Configure Jupyter to display the assigned value after an assignment\n",
    "%config InteractiveShell.ast_node_interactivity='last_expr_or_assign'\n",
    "\n",
    "# import functions from the modsim library\n",
    "from modsim import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pandas import read_html\n",
    "\n",
    "filename = 'data/World_population_estimates.html'\n",
    "tables = read_html(filename, header=0, index_col=0, decimal='M')\n",
    "table2 = tables[2]\n",
    "table2.columns = ['census', 'prb', 'un', 'maddison', \n",
    "                  'hyde', 'tanton', 'biraben', 'mj', \n",
    "                  'thomlinson', 'durand', 'clark']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_results(census, un, timeseries, title):\n",
    "    \"\"\"Plot the estimates and the model.\n",
    "    \n",
    "    census: TimeSeries of population estimates\n",
    "    un: TimeSeries of population estimates\n",
    "    timeseries: TimeSeries of simulation results\n",
    "    title: string\n",
    "    \"\"\"\n",
    "    plot(census, ':', label='US Census')\n",
    "    plot(un, '--', label='UN DESA')\n",
    "    if len(timeseries):\n",
    "        plot(timeseries, color='gray', label='model')\n",
    "    \n",
    "    decorate(xlabel='Year', \n",
    "             ylabel='World population (billion)',\n",
    "             title=title)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "un = table2.un / 1e9\n",
    "census = table2.census / 1e9\n",
    "empty = TimeSeries()\n",
    "plot_results(census, un, empty, 'World population estimates')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "half = get_first_value(census) / 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "init = State(young=half, old=half)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "system = System(birth_rate1 = 1/18,\n",
    "                mature_rate = 1/40,\n",
    "                death_rate = 1/40,\n",
    "                t_0 = 1950,\n",
    "                t_end = 2016,\n",
    "                init=init)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_func1(state, t, system):\n",
    "    births = system.birth_rate1 * state.young\n",
    "        \n",
    "    maturings = system.mature_rate * state.young\n",
    "    deaths = system.death_rate * state.old\n",
    "    \n",
    "    young = state.young + births - maturings\n",
    "    old = state.old + maturings - deaths\n",
    "    \n",
    "    return State(young=young, old=old)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "state = update_func1(init, system.t_0, system)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "state = update_func1(state, system.t_0, system)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def run_simulation(system, update_func):\n",
    "    \"\"\"Simulate the system using any update function.\n",
    "    \n",
    "    init: initial State object\n",
    "    system: System object\n",
    "    update_func: function that computes the population next year\n",
    "    \n",
    "    returns: TimeSeries\n",
    "    \"\"\"\n",
    "    results = TimeSeries()\n",
    "    \n",
    "    state = system.init\n",
    "    results[system.t_0] = state.young + state.old\n",
    "    \n",
    "    for t in linrange(system.t_0, system.t_end):\n",
    "        state = update_func(state, t, system)\n",
    "        results[t+1] = state.young + state.old\n",
    "        \n",
    "    return results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "results = run_simulation(system, update_func1);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_results(census, un, results, 'World population estimates')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
